package com.finance.util;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.alibaba.druid.pool.DruidDataSource;


import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
 * @ClassName: CodeAutoCreate
 * @Description: 代码生成器
 * @author gyw
 */
public class CodeAutoCreate {
	private static final Logger log =  Logger.getLogger(CodeAutoCreate.class);
	//数据库配置
	private static String URL="jdbc:mysql://114.55.42.193:3306/finance";
	private static String USER="root";
	private static String PASSSWD="root";

	//修改相关配置
	private static String TABLE_NAME = "biz_logistics_error_log";
	private static String MODULE_NAME = "report";
	private static String PACKAGE_NAME = "com/finance";
	private static String COM_NAME="report";
	private static String CLASS_NAME = "LogisticsError";
	private static String LOWCLASS_NAME = "logisticsError";

	private static final String OUT_DIR = System.getProperty("user.dir")+"/out";


	public static void main(String[] args) throws SQLException, InterruptedException, IOException {
		Configuration cfg = new Configuration();
		cfg.setDirectoryForTemplateLoading(new File(System.getProperty("user.dir")+"/core/templates"));
		log.debug("清空原文件内容"+(delDir(new File(OUT_DIR))?"成功":"失败"));
		Thread.sleep(1000);
		List<Map<String,String>> colList=new ArrayList<Map<String, String>>();

		//由于当前框架无法从配置中获取，所以只能手工加入。
		DruidDataSource dataSource = new DruidDataSource();
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUrl(URL);
		dataSource.setUsername(USER);
		dataSource.setPassword(PASSSWD);
		final String sql = "select  column_name,data_type , column_comment, numeric_scale   from information_schema.columns  where   table_name='"+TABLE_NAME+"'";
		ResultSet rs= dataSource.getConnection().createStatement().executeQuery(sql);
		while (rs.next()) {
			String colName = rs.getString("column_name");
			String dataType = rs.getString("data_type").toUpperCase();
			String comment = rs.getString("column_comment");
			String numericScale = rs.getString("numeric_scale");
			int numericScaleInt = 0;
			if (!StringUtils.isEmpty(numericScale)) {
				numericScaleInt = Integer.parseInt(numericScale);
			}
			Map<String, String> m = new HashMap<String,String>();
			colName= colName.toLowerCase();
			m.put("colName", colName);
			if("INT".equals(dataType.toUpperCase())){
				dataType="INTEGER";
			}
			m.put("dataType", dataType.toUpperCase());
			m.put("fieldType", transform(dataType.toUpperCase(), numericScaleInt));
			m.put("fieldName", underlineToCamel(colName,false));
			m.put("fieldNameUp",underlineToCamel(colName,true));
			m.put("comment", comment);
			m.put("numericScale", String.valueOf(numericScaleInt));
			colList.add(m);
		}
		log.debug("初始化完成............");
		CLASS_NAME=(CLASS_NAME.length()==0?underlineToCamel(TABLE_NAME.toLowerCase(),true):CLASS_NAME);
		LOWCLASS_NAME=LOWCLASS_NAME.length()==0?underlineToCamel(TABLE_NAME.toLowerCase(),false):LOWCLASS_NAME;
		Map root = new HashMap();
		root.put("tableName", TABLE_NAME);
		root.put("packageName", PACKAGE_NAME.replace("/", "."));
		root.put("className", CLASS_NAME);
		root.put("lowClassName", LOWCLASS_NAME);
		root.put("comName", COM_NAME);
		root.put("moduleName",MODULE_NAME);
		root.put("colList", colList);
		root.put("firstCol", ((HashMap)colList.get(0)).get("colName"));
		root.put("firstParam", underlineToCamel(((HashMap)colList.get(0)).get("colName").toString(),false));
		root.put("firstColType", transform(((HashMap)colList.get(0)).get("dataType").toString(), Integer.parseInt(((HashMap)colList.get(0)).get("numericScale").toString())));
		boolean result = geneJavaFile(cfg,"sqlRead.htm",root, "/mapper/"+MODULE_NAME+"/read/",CLASS_NAME+"Mapper.xml");
		result=result&& geneJavaFile(cfg,"sqlWirte.htm",root, "/mapper/"+MODULE_NAME+"/wirte/",CLASS_NAME+"Mapper.xml");
		result=result&& geneJavaFile(cfg,"dao.htm",root, "/mmd_src/"+PACKAGE_NAME+"/"+MODULE_NAME+"/dao",CLASS_NAME+"Mapper.java");
		result=result&& geneJavaFile(cfg,"serviceI.htm",root,"/service_src/"+PACKAGE_NAME+"/"+MODULE_NAME+"/IService","I"+CLASS_NAME+"Service.java");
		result=result&& geneJavaFile(cfg,"service.htm",root,"/service_src/"+PACKAGE_NAME+"/"+MODULE_NAME+"/Service",CLASS_NAME+"Service.java");
        result=result&& geneJavaFile(cfg,"vo.htm",root,"/mmd_src/"+PACKAGE_NAME+"/"+MODULE_NAME+"/model",CLASS_NAME+".java");

        //result=result&& geneJavaFile(cfg,"bo.htm",root,"/mmd_src/"+PACKAGE_NAME+"/"+MODULE_NAME+"/bo",CLASS_NAME+"Bo.java");
		//result=result&& geneJavaFile(cfg,"dto.htm",root,"/mmd_src/"+PACKAGE_NAME+"/"+MODULE_NAME+"/dto",CLASS_NAME+"Dto.java");
		//result=result&& geneJavaFile(cfg,"manage.htm",root,"/mmd_src/"+PACKAGE_NAME+"/"+MODULE_NAME+"/manage",CLASS_NAME+"Manage.java");

		if(result) {
            log.info("代码生成结束............");
        }
	}
	public static String transform(String fieldType, int presicion){
		String result="";
		switch (fieldType) {
			case "TINYINT":
				result="int";
				break;
			case "INTEGER":
				result="int";
				break;
			case "BIGINT":
				result="long";
				break;
			case "VARCHAR":
				result="String";
				break;
			case "TIMESTAMP":
				result="Timestamp";
				break;
			case "DATE":
				result="Date";
				break;
			case "CHAR":
				result="String";
				break;
			case "DECIMAL":
				if (presicion > 0) {
					result = "double";
				} else {
					result = "Long";
				}
				break;
			default:
				result="String";
				break;
		}
		return result;
	}

	public static boolean creatDirs(String aParentDir, String aSubDir) {
		File aFile = new File(aParentDir);
		if (aFile.exists()) {
			File aSubFile = new File(aParentDir + aSubDir);
			if (!aSubFile.exists()) {
				return aSubFile.mkdirs();
			} else {
				return true;
			}
		} else {
			return false;
		}
	}

	public static  boolean delDir(File file){
		if(!file.exists()){
			file.mkdir();
		}
		while (file.list()!=null && file.list().length>0) {
			File[] a=file.listFiles();
			for (int i = 0; a!=null&&i < a.length; i++) {
				if(a[i].isDirectory()&&a[i].list()!=null&&a[i].list().length>0){
					delDir(a[i]);
				}else{
					a[i].delete();
				}

			}
		}
		return true;
	}

	public static boolean geneJavaFile(Configuration cfg,String templateFileName, Map propMap, String htmlFilePath, String htmlFileName) {
		try {
			Template t = cfg.getTemplate(templateFileName,"UTF-8");

			creatDirs(OUT_DIR, htmlFilePath);

			File afile = new File(OUT_DIR + "/" + htmlFilePath + "/"+ htmlFileName);

			Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(afile),"UTF-8"));

			t.process(propMap, out);
		} catch (TemplateException e) {
			log.error("Error while processing FreeMarker template "
					+ templateFileName, e);
			return false;
		} catch (IOException e) {
			log.error("Error while generate Static Html File "
					+ htmlFileName, e);
			return false;
		}

		return true;
	}

	public static final char UNDERLINE = '_';

	public static String camelToUnderline(String param) {
		if (param == null || "".equals(param.trim())) {
			return "";
		}
		int len = param.length();
		StringBuilder sb = new StringBuilder(len);
		for (int i = 0; i < len; i++) {
			char c = param.charAt(i);
			if (Character.isUpperCase(c)) {
				sb.append(UNDERLINE);
				sb.append(Character.toLowerCase(c));
			} else {
				sb.append(c);
			}
		}
		return sb.toString();
	}

	public static String underlineToCamel(String param,boolean firstCharUp) {
		if (param == null || "".equals(param.trim())) {
			return "";
		}
		int len = param.length();
		StringBuilder sb = new StringBuilder(len);

		for (int i = 0; i < len; i++) {
			char c = param.charAt(i);
			if(i==0&&firstCharUp){
				Character ch = new Character(c);
				c = Character.toUpperCase(c);
			}
			if (c == UNDERLINE) {
				if (++i < len) {
					sb.append(Character.toUpperCase(param.charAt(i)));
				}
			} else {
				sb.append(c);
			}
		}
		return sb.toString();
	}

}
